using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.Windows.Forms;
using Jonathan.Classes;
using System.Text;
using System.Drawing;
using System.Collections;
using System.Xml;

//using mshtml;

namespace Jonathan.Controls
{
   /// <summary>
   /// An extended WebBrowser.
   /// </summary>
   public class Webber : WebBrowser
   {
      #region - Fields -

      private string m_Html;
      private FrmMain m_FormMain;
      private IWebberHost m_Host;
      private fHtmlToolTip m_MoToolTip;
      private bool m_TtShown;
      private HtmlElement m_MouseClickElement;

      #endregion

      #region - Constructor / Setup -

      /// <summary>
      /// Creates a new Webber Control.
      /// </summary>
      public Webber ()
      {
         this.Navigate ("about:Blank");
         while (this.Document.Body == null) Application.DoEvents ();
         this.m_Html = "";
      }

      /// <summary>
      /// Sets up the Webber Control.
      /// </summary>
      /// <param name="main">Reference to Main From.</param>
      /// <param name="host">The Control that hosts this webber.</param>
      public void SetupWebber (FrmMain main, IWebberHost host)
      {
         this.m_FormMain = main;
         this.m_Host = host;
         if (host != null)
         {
            this.ContextMenuStrip = host.GetContextMenu ();
         }
         this.m_MoToolTip = null;
         this.m_TtShown = false;

         if (this.Document != null)
         {
            this.Document.MouseUp += DocumentMouseUp;
            this.Document.MouseDown += DocumentMouseDown;
            this.Document.MouseOver += DocumentMouseOver;
         }
         this.Resize += WebberResize;

         this.AllowNavigation = false;
         this.AllowWebBrowserDrop = false;
         this.IsWebBrowserContextMenuEnabled = false;
      }

      /// <summary>
      /// Occurs when the WebBrowser is resized.
      /// </summary>
      /// <param name="sender">WebBrowser (this).</param>
      /// <param name="e">Event Arguments.</param>
      void WebberResize (object sender, EventArgs e)
      {
         if (this.Document != null)
            this.Document.InvokeScript ("resizeJonathan");
      }

      #endregion

      #region - Mouse Over -

      /// <summary>
      /// Occurs when the mouse is over the document...
      /// </summary>
      /// <param name="sender">Document</param>
      /// <param name="e">HtmlElementEventArgs</param>
      void DocumentMouseOver (object sender, HtmlElementEventArgs e)
      {
         if (this.m_FormMain.ProgramData.MouseOverToolTips)
         {
            if (e.ToElement != null)
            {
               if (e.ToElement.TagName.Equals ("A"))
               {
                  if (Common.IsNumeric (e.ToElement.InnerText))
                  {
                     this.ShowStrongsTt (e, true);
                  }
                  else if (e.ToElement.InnerText.StartsWith ("see GREEK"))
                  {
                     string num = e.ToElement.InnerText.Substring (e.ToElement.InnerText.LastIndexOf (' ') + 1);
                     num = num.TrimStart ('0');
                     CreateStrongsTt (e, num, "Greek", true);
                  }
                  else if (e.ToElement.InnerText.StartsWith ("see HEBREW"))
                  {
                     string num = e.ToElement.InnerText.Substring (e.ToElement.InnerText.LastIndexOf (' ') + 1);
                     num = num.TrimStart ('0');
                     CreateStrongsTt (e, num, "Hebrew", true);
                  }
                  else if (e.ToElement.OuterHtml.IndexOf ("<A href=\"wordref\">") == 0)
                  {
                     this.CloseTt ();
                  }
                  else if (e.ToElement.OuterHtml.Contains ("class=goto"))
                  {
                     this.CloseTt ();
                  }
                  else
                  {
                     CreateMoScriptureTt (e.ToElement, e);
                  }
               }
               else
               {
                  this.CloseTt ();
               }
            }
         }
      }

      #endregion

      #region - Close ToolTip -

      /// <summary>
      /// Close the Tool Tip if Open...
      /// </summary>
      private void CloseTt ()
      {
         if (this.m_TtShown)
         {
            this.m_MoToolTip.Close ();
            this.m_MoToolTip.Dispose ();
            this.m_MoToolTip = null;
            this.m_TtShown = false;
         }
      }

      #endregion

      #region - Mouse Down -

      /// <summary>
      /// Occurs when the mouse is released...
      /// </summary>
      /// <param name="sender">Document</param>
      /// <param name="e">HtmlElementEventArgs</param>
      void DocumentMouseDown (object sender, HtmlElementEventArgs e)
      {
         if (e.MouseButtonsPressed == MouseButtons.Right)
         {
            this.m_MouseClickElement = this.ActiveElement;
            if (this.Selection.Equals (string.Empty) && !this.ActiveElement.TagName.Equals ("TEXTAREA"))
               this.SelectWord ();
         }

         if (this.m_Host.GetType () == typeof (CtrlSearch))
         {
            if (this.Document != null)
            {
               HtmlElement hel = this.Document.GetElementFromPoint (e.MousePosition);
               if (hel != null)
               {
                  if (e.MouseButtonsPressed == MouseButtons.Left)
                     this.HighlightRow (hel, e.CtrlKeyPressed, false);
                  else if (!e.CtrlKeyPressed)
                     this.HighlightRow (hel, false, true);
               }
            }
         }
      }

      #endregion

      #region - Mouse Up -

      /// <summary>
      /// Occurs when the mouse is released...
      /// </summary>
      /// <param name="sender">Document</param>
      /// <param name="e">HtmlElementEventArgs</param>
      void DocumentMouseUp (object sender, HtmlElementEventArgs e)
      {
         if (e.MouseButtonsPressed == MouseButtons.Left)
         {
            if (this.ActiveElement.TagName.Equals ("A"))
            {
               XmlDocument xDoc = GetXmlDoc ();
               XmlAttribute hrefAtt = xDoc.ChildNodes[0].Attributes["href"];

               if (Common.IsNumeric (xDoc.InnerText))
               {
                  this.ShowStrongsTt (e, false);
               }
               else if (xDoc.InnerText.StartsWith ("see GREEK"))
               {
                  string num = xDoc.InnerText.Substring (xDoc.InnerText.LastIndexOf (' ') + 1);
                  num = num.TrimStart ('0');
                  CreateStrongsTt (e, num, "Greek", false);
               }
               else if (xDoc.InnerText.StartsWith ("see HEBREW"))
               {
                  string num = xDoc.InnerText.Substring (xDoc.InnerText.LastIndexOf (' ') + 1);
                  num = num.TrimStart ('0');
                  CreateStrongsTt (e, num, "Hebrew", false);
               }
               else if (hrefAtt != null)
               {
                  XmlAttribute classAtt = xDoc.ChildNodes[0].Attributes["class"];
                  if (hrefAtt.Value.Equals ("wordref", StringComparison.CurrentCultureIgnoreCase))//this.ActiveElement.OuterHtml.IndexOf("<A href=\"wordref\">") == 0)
                  {
                     if (this.m_Host != null)
                     {
                        if (e.CtrlKeyPressed)
                        {
                           this.m_FormMain.StartReference (this.m_Host.GetVersion (0), xDoc.InnerText, this.m_Host.GetTabPage ());
                        }
                        else
                        {
                           bool selected = this.m_Host.SelectRefWord (xDoc.InnerText, false);
                           // This is for easton's BD, sometimes we will have a word that ends in 's', and the word in the list will not...
                           if (!selected && xDoc.InnerText.ToLower ().EndsWith ("s"))
                              selected = this.m_Host.SelectRefWord (xDoc.InnerText.Substring (0, xDoc.InnerText.Length - 1), false);
                           // This is for easton's BD, sometimes the ref word does not match the word in the list correctly...
                           if (!selected)
                              this.m_Host.SelectRefWord (xDoc.InnerText, true);
                        }
                     }
                  }
                  else if (classAtt != null)
                  {
                     if (classAtt.Value.Equals ("goto", StringComparison.CurrentCultureIgnoreCase))
                     {
                        string pass = xDoc.ChildNodes[0].Attributes["title"].Value;
                        List<CPassage> passages = Parser.Parse (pass.Substring (pass.IndexOf (' ')).Trim ());
                        if (passages.Count > 0)
                        {
                           passages[0].Version = hrefAtt.Value;
                           this.m_FormMain.StartBible (passages, null);

                           if (this.m_Host.GetType () == typeof (fHtmlToolTip))
                           {
                              fHtmlToolTip tt = (fHtmlToolTip)this.m_Host;
                              tt.Close ();
                           }
                        }
                     }
                  }
                  else
                  {
                     CreateScriptureTt (e);
                  }
               }
            }
            else if (this.ActiveElement.OuterText != null && this.ActiveElement.OuterText.Equals ("TSK"))
            {
               this.ToggleTsk ();
            }
            else if (this.ActiveElement.TagName.Equals ("BUTTON"))
            {
               //TODO: SaveVerseNotes ();
            }
         }
      }

      #endregion

      #region - Show Strong's Tool Tip -

      /// <summary>
      /// Shows a Tool Tip of a Strong's number.
      /// </summary>
      /// <param name="e">HtmlElementEventArgs</param>
      /// <param name="mouseOver">Is this on a mouse over action or not.</param>
      private void ShowStrongsTt (HtmlElementEventArgs e, bool mouseOver)
      {
         HtmlElement elTr = Common.GetTrElement (this);
         int index;
         string book = "";
         if ((index = elTr.OuterHtml.IndexOf ("passage")) != -1)
         {
            string passage = elTr.OuterHtml.Substring (index + 9, elTr.OuterHtml.IndexOf (">") - 10 - index);
            book = passage.Split ('|')[0];
         }
         if (!string.IsNullOrEmpty (book))
         {
            CreateStrongsTt (e, this.ActiveElement.InnerText, Parser.IsBookNewTestament (book) ? "Greek" : "Hebrew", mouseOver);
         }
      }

      #endregion

      #region - Save Verse Notes -

      /*/// <summary>
      /// Saves the Notes of a specific verse.
      /// </summary>
      private void SaveVerseNotes ()
      {
         HtmlElement hDiv = this.ActiveElement.Parent;
         int index;
         string dest = "";
         if (hDiv != null)
         {
            if ((index = hDiv.OuterHtml.IndexOf ("id")) != -1)
               dest = hDiv.OuterHtml.Substring (index + 3, hDiv.OuterHtml.IndexOf (">") - 3 - index);
         }

         string[] noteInfo = dest.Split ('|');

         Database dbVerseNotes = new Database (Common.DataFolder + Common.DATABASE_VERSE_NOTES);
         Query qVerseNotes = new Query (QueryType.SELECT, Common.TABLE_NOTES);
         qVerseNotes.SELECT ("Verse");
         qVerseNotes.SELECT ("Note");
         qVerseNotes.WHERE ("Book", Operator.EQUALS, noteInfo[1]);
         qVerseNotes.WHERE ("Chapter", Operator.EQUALS, noteInfo[2]);
         qVerseNotes.WHERE ("Verse", Operator.EQUALS, noteInfo[3]);
         dbVerseNotes.RunQuery (qVerseNotes);
         string note = hDiv.FirstChild.InnerText;

         if (qVerseNotes.RowsReturned == 0)
         {
            if (!string.IsNullOrEmpty (note))
            {
               ArrayList row = new ArrayList ();
               row.Add (noteInfo[1]);
               row.Add (noteInfo[2]);
               row.Add (noteInfo[3]);
               row.Add (note);

               dbVerseNotes.Insert (Common.TABLE_NOTES, row);
            }
         }
         else
         {
            Query qUpdate;
            if (!string.IsNullOrEmpty (note))
            {
               qUpdate = new Query (QueryType.UPDATE, Common.TABLE_NOTES);
               qUpdate.SET ("Note", note);
            }
            else
               qUpdate = new Query (QueryType.DELETE, Common.TABLE_NOTES);

            qUpdate.WHERE ("Book", Operator.EQUALS, noteInfo[1]);
            qUpdate.WHERE ("Chapter", Operator.EQUALS, noteInfo[2]);
            qUpdate.WHERE ("Verse", Operator.EQUALS, noteInfo[3]);
            dbVerseNotes.RunQuery (qUpdate);
         }

         dbVerseNotes.Commit ();
         hDiv.InnerHtml = note;
         if (string.IsNullOrEmpty (note))
            hDiv.Parent.Parent.Style = "DISPLAY: none";
      }*/

      #endregion

      #region - Toggle TSK -

      /// <summary>
      /// Toggles if the Treasury of Scripture Knowledge is shown or not.
      /// </summary>
      private void ToggleTsk ()
      {
         string oHtml = this.ActiveElement.InnerHtml;
         int index;
         string dest = "";
         if ((index = oHtml.IndexOf ("destina")) != -1)
            dest = oHtml.Substring (index + 9, oHtml.IndexOf (">") - 10 - index);

         if (!string.IsNullOrEmpty (dest))
         {
            HtmlElement destEl = this.Document.GetElementById (dest);
            if (destEl != null)
            {
               if (string.IsNullOrEmpty (destEl.InnerHtml))
               {
                  string[] info = dest.Split ('|');
                  using (SQLiteConnection dbConn = new SQLiteConnection(Common.ConnString (Common.DataFolder + 
                     this.m_FormMain.ProgramData.Tsk.Path)))
                  {
                     dbConn.Open ();
                     SQLiteCommand command = dbConn.CreateCommand ();
                     command.CommandText = string.Format ("SELECT Text FROM book_text WHERE Book='{0}' AND Chapter={1} AND Verse={2}", info[1], info[2], info[3]);
                     using (SQLiteDataReader reader = command.ExecuteReader())
                     {
                        if (reader.Read ())
                        {
                           string tskText = reader.GetString (0).Trim ();
                           destEl.Parent.Parent.Style = "DISPLAY: block";
                           destEl.Parent.Parent.FirstChild.Style = "BACKGROUND: #D8D8D8";
                           destEl.Parent.Parent.FirstChild.InnerHtml = "<span style=\"writing-mode: tb-rl;filter: flipv fliph;font-weight:bolder;\">TSK</span>";
                           destEl.InnerHtml = !string.IsNullOrEmpty (tskText)
                                                 ? tskText
                                                 : "<strong>No references for this verse.</strong>";
                        }
                     }
                  }
               }
               else
               {
                  destEl.Parent.Parent.Style = "DISPLAY: none";
                  destEl.Parent.Parent.FirstChild.Style = "BACKGROUND: #FCFDFE";
                  destEl.Parent.Parent.FirstChild.InnerHtml = "";
                  destEl.InnerHtml = "";
               }
            }
         }
      }

      #endregion

      #region - Get XML Document -

      /// <summary>
      /// Gets an xml document for the active element
      /// </summary>
      /// <returns>XmlDocument with the active element parsed.</returns>
      private XmlDocument GetXmlDoc ()
      {
         string xmlToParse = this.ActiveElement.OuterHtml;
         int pos = 0;
         int parseIndex = xmlToParse.IndexOf ('=', pos);
         while (parseIndex != -1)
         {
            if (xmlToParse[parseIndex + 1] != '\"')
            {
               xmlToParse = xmlToParse.Insert (parseIndex + 1, "\"");
               parseIndex = xmlToParse.IndexOf (' ', parseIndex);
               xmlToParse = xmlToParse.Insert (parseIndex, "\"");
            }
            pos = parseIndex + 1;
            parseIndex = xmlToParse.IndexOf ('=', pos);
         }
         XmlDocument xDoc = new XmlDocument ();
         xDoc.LoadXml (xmlToParse);
         return xDoc;
      }

      #endregion

      #region - Highlight Row -

      /// <summary>
      /// Highlightes the Row...
      /// </summary>
      private void HighlightRow (HtmlElement clickElement, bool ctrlKeyPressed, bool rightMouse)
      {
         HtmlElement elTable = this.GetParentElement (clickElement, "TABLE");
         if (elTable != null)
         {
            elTable = this.GetParentElement (clickElement, "TR");
            if (elTable == null)
               return;
            if (elTable.FirstChild.TagName.Equals ("TH"))
               return;

            if (rightMouse && !string.IsNullOrEmpty (elTable.Style))
               return;

            if (!ctrlKeyPressed)
            {
               // Clear all Highlighting...
               HtmlElementCollection hEls = this.Document.GetElementsByTagName ("TR");
               foreach (HtmlElement hel in hEls)
               {
                  if (!string.IsNullOrEmpty (hel.Style))
                     hel.Style = "";
               }
            }
            else if (!string.IsNullOrEmpty (elTable.Style))
            {
               elTable.Style = "";
               return;
            }

            elTable.Style = "background: #C0CFE2;";
         }
      }

      #endregion

      #region - Get Parent Html Element -

      /// <summary>
      /// Gets the Parent Element with the desired tag...
      /// </summary>
      /// <param name="startEl">Starting Child Element.</param>
      /// <param name="wantedTag">Tag of Desired Parent</param>
      /// <returns>Parent Element.</returns>
      public HtmlElement GetParentElement (HtmlElement startEl, string wantedTag)
      {
         if (startEl == null)
            return null;

         HtmlElement el = startEl;
         while (!el.TagName.Equals (wantedTag))
         {
            if (el.Parent == null)
               return null;
            el = el.Parent;
         }

         return el;
      }

      #endregion

      #region - Strongs Tool Tip -

      /// <summary>
      /// Creates a tool Tip with the given strong's number.
      /// </summary>
      /// <param name="e">HtmlElementEventArgs.</param>
      /// <param name="num">Strongs Number.</param>
      /// <param name="horg">Original Html Text.</param>
      /// <param name="mouseOver">If we are in mouse over mode, this makes sure the  tool will close if already shown.</param>
      private void CreateStrongsTt (HtmlElementEventArgs e, string num, string horg, bool mouseOver)
      {
         if (mouseOver)
         {
            if (this.m_TtShown)
            {
               if (e.ToElement != null)
               {
                  if (this.m_MoToolTip.Tag.ToString ().Equals (e.ToElement.InnerText))
                  {
                     return;
                  }
               }
               this.m_MoToolTip.Close ();
               this.m_MoToolTip.Dispose ();
               this.m_MoToolTip = null;
               this.m_TtShown = false;
            }
         }
         foreach (CjData.IcDbInfo dbI in this.m_FormMain.ProgramData.ReferenceDatabases)
         {
            if (dbI.Name.StartsWith ("Strong's " + horg))
            {
               using (SQLiteConnection dbConn = new SQLiteConnection(Common.ConnString (Common.DataFolder + dbI.Path)))
               {
                  dbConn.Open ();
                  SQLiteCommand command = dbConn.CreateCommand ();
                  command.CommandText = string.Format ("SELECT * FROM book_text WHERE Notes={0}", num);
                  SQLiteDataReader reader = command.ExecuteReader ();
                  if (reader.Read ())
                  {
                     string text = reader.GetString (reader.GetOrdinal ("Text"));
                     string word = reader.GetString (reader.GetOrdinal ("Word"));
                     StringBuilder html = new StringBuilder ();
                     html.Append ("<table><tr><td>");
                     html.Append (text);
                     html.Append ("</td></tr></table>");
                     if (mouseOver)
                     {
                        this.m_TtShown = true;

                        this.m_MoToolTip = new fHtmlToolTip (this.m_FormMain, this.PointToScreen (e.ClientMousePosition),
                            html.ToString (), word + " (" + num + ")", false);
                        this.m_MoToolTip.Tag = e.ToElement.InnerText;
                        this.m_MoToolTip.ShowTT ();
                     }
                     else
                     {
                        fHtmlToolTip tt = new fHtmlToolTip (this.m_FormMain, this.PointToScreen (e.ClientMousePosition),
                            html.ToString (), word + " (" + num + ")", true);
                        tt.ShowTT ();
                     }
                  }
               }
               break;
            }
         }
      }

      #endregion

      #region - Scripture ToolTip -

      /// <summary>
      /// Creates a tool tip for the clicked element.
      /// </summary>
      /// <param name="e">HtmlElementEventArgs</param>
      private void CreateScriptureTt (HtmlElementEventArgs e)
      {
         this.CloseTt ();
         //StringBuilder sb = GetPassageText(this.ActiveElement);

         fHtmlToolTip tt = GetPassageText (this.ActiveElement, e.ClientMousePosition, true);
         //new fHtmlToolTip(this.m_FormMain, this.PointToScreen(e.ClientMousePosition), sb.ToString(), this.ActiveElement.InnerText, true);
         tt.ShowTT ();
      }

      /// <summary>
      /// Creates a tool tip for the given element.
      /// </summary>
      /// <param name="e">Html Element to create Tool Tip for.</param>
      /// <param name="eAr">HtmlElementEventArgs</param>
      private void CreateMoScriptureTt (HtmlElement e, HtmlElementEventArgs eAr)
      {
         if (this.m_TtShown)
         {
            if (this.m_MoToolTip.Title.Equals (e.InnerText))
            {
               return;
            }
            this.m_MoToolTip.Close ();
            this.m_MoToolTip.Dispose ();
            this.m_MoToolTip = null;
            this.m_TtShown = false;
         }

         this.m_TtShown = true;
         //StringBuilder sb = GetPassageText(e);

         this.m_MoToolTip = GetPassageText (e, eAr.ClientMousePosition, false); /*new fHtmlToolTip(this.m_FormMain, this.PointToScreen(eAr.ClientMousePosition), sb.ToString(),
                e.InnerText, false);*/
         this.m_MoToolTip.ShowTT ();
      }

      #endregion

      #region - Get Passage Text -

      /// <summary>
      /// Gets the text for the passage in question...
      /// </summary>
      /// <param name="e">HtmlElement with corresponding passage(s).</param>
      /// <param name="pos">Position to place tool tip.</param>
      /// <param name="closebutton">True to add a close button to the tool tip.</param>
      /// <returns>Newly created Tool Tip</returns>
      private fHtmlToolTip GetPassageText (HtmlElement e, Point pos, bool closebutton)
      {
         List<CPassage> passages = Parser.Parse (e.InnerText);

         string path = "";
         string source = "";
         if (this.m_Host != null)
         {
            path = this.m_Host.GetVersionPath (-1);
            source = this.m_Host.GetVersion (-1);
         }

         if (string.IsNullOrEmpty (path))
         {
            // Get the Cell...
            HtmlElement elTd = this.ActiveElement;
            while (!elTd.TagName.Equals ("TD"))
            {
               if (elTd.Parent == null)
                  return null;
               elTd = elTd.Parent;
            }
            int index;
            if ((index = elTd.OuterHtml.IndexOf ("version=")) != -1)
            {
               path = elTd.OuterHtml.Substring (index + 9, elTd.OuterHtml.IndexOf (">") - 10 - index);
               source = this.m_Host.GetVersion (Convert.ToInt32 (path));
               path = this.m_Host.GetVersionPath (Convert.ToInt32 (path));
            }
         }

         SQLiteConnection dbConn;
         if (this.m_Host == null || string.IsNullOrEmpty (path))
         {
            dbConn = new SQLiteConnection (Common.ConnString(this.m_FormMain.DefaultBibleFile));
            source = this.m_FormMain.ProgramData.DefaultBible;
         }
         else
         {
            dbConn = new SQLiteConnection (Common.ConnString(path));
         }
         dbConn.Open ();
         StringBuilder sb = Common.GetToolTipText (passages, source, dbConn.CreateCommand ());

         fHtmlToolTip tt = new fHtmlToolTip (this.m_FormMain, this.PointToScreen (pos), sb.ToString (), e.InnerText, closebutton);
         tt.SetVersionPath (path);
         return tt;
         //return sb;
      }

      #endregion

      #region - Public Properties -

      /// <summary>
      /// Gets the Active Element that was Clicked...
      /// </summary>
      public HtmlElement MouseClickElement
      {
         get { return this.m_MouseClickElement; }
      }

      /// <summary>
      /// Gets the current selection.
      /// </summary>
      public string Selection
      {
         get
         {
            return this.Document.InvokeScript ("getTextSelection").ToString ().Trim ();
         }
      }

      /// <summary>
      /// Gets or Sets the Inner HTML of the document.
      /// </summary>
      public string innerHTML
      {
         get { return this.Document.Body.InnerHtml; }
         set { this.Document.Body.InnerHtml = value; }
      }

      /// <summary>
      /// Gets or Sets the Inner Text of the Document.
      /// </summary>
      public string innerTEXT
      {
         get { return this.Document.Body.InnerText; }
         set { this.Document.Body.InnerText = value; }
      }

      /// <summary>
      /// Gets or Sets the HTML of the document giving the ability to use CSS and scripts.
      /// </summary>
      public string HTML
      {
         get { return this.m_Html; }

         set
         {
            this.m_Html = value;
            this.Document.OpenNew (true);
            this.Document.Write (value);
            this.Document.InvokeScript ("resizeJonathan");
            /* Old Code using mshtml to load a web document. This makes javascript work automatically!
         * mshtml.IHTMLDocument2 doc = (mshtml.IHTMLDocument2)this.Document.DomDocument;
             * doc.write(value);
             * doc.close();*/
         }
      }

      /// <summary>
      /// Gets the Body of the document.
      /// </summary>
      public HtmlElement Body
      {
         get { return this.Document.Body; }
      }

      /// <summary>
      /// Gets the Active Element of the document.
      /// </summary>
      public HtmlElement ActiveElement
      {
         get { return this.Document.ActiveElement; }
      }

      #endregion

      #region - Public Methods -

      /// <summary>
      /// Select the word clicked.
      /// </summary>
      public void SelectWord ()
      {
         this.Document.InvokeScript ("expandSelection");
      }

      /// <summary>
      /// Clear any selection.
      /// </summary>
      public void ClearSelection ()
      {
         this.Document.ExecCommand ("Unselect", false, null);
      }

      /// <summary>
      /// Copy Current Selection.
      /// </summary>
      public void Copy ()
      {
         this.Document.ExecCommand ("Copy", false, null);
         ClearSelection ();
      }

      /// <summary>
      /// Paste data from the clipboard.
      /// </summary>
      public void Paste ()
      {
         this.Document.ExecCommand ("Paste", false, null);
      }

      /// <summary>
      /// Cut Current Selection.
      /// </summary>
      public void Cut ()
      {
         this.Document.ExecCommand ("Cut", false, null);
      }

      /// <summary>
      /// Select Everything in the Document.
      /// </summary>
      public void SelectAll ()
      {
         this.Document.ExecCommand ("SelectAll", false, null);
      }

      /// <summary>
      /// Finds occurances of the given text.
      /// </summary>
      /// <param name="text">Text to find.</param>
      /// <returns>Found or not Found</returns>
      public void FindNext (string text)
      {
         this.Document.InvokeScript ("findString", new object[] { text });
      }

      /// <summary>
      ///  Highlight All occurances of the given text.
      /// </summary>
      /// <param name="text">Text to highlight.</param>
      /// <param name="caseSensitive">Is h</param>
      public void Highlight (string text, bool caseSensitive)
      {
         StringBuilder html = new StringBuilder ();
         string tempHtml = (caseSensitive) ? this.Document.Body.InnerHtml : this.Document.Body.InnerHtml.ToLower ();
         if (!caseSensitive)
            text = text.ToLower ();

         int start = 0;
         int lastFind = 0;
         while ((start = tempHtml.IndexOf (text, start)) != -1)
         {
            html.Append (this.innerHTML.Substring (lastFind, start - lastFind));
            html.Append ("<span style=\"background: yellow;\">");
            html.Append (this.innerHTML.Substring (start, text.Length));
            html.Append ("</span>");
            start += text.Length;
            lastFind = start;
         }

         html.Append (this.innerHTML.Substring (lastFind, this.innerHTML.Length - lastFind));
         this.Document.Body.InnerHtml = html.ToString ();
      }

      #endregion
   }
}
